package com.code2roc.miniflow.base.util;

import com.code2roc.miniflow.base.model.MiniFlowSQLInfo;
import com.code2roc.miniflow.app.IMiniFlowDataBaseBridge;

import java.lang.reflect.Field;
import java.util.*;

public class MiniFlowJDBCUtil {
    private static IMiniFlowDataBaseBridge bridge;

    public static void init(IMiniFlowDataBaseBridge dataBaseBridge) {
        bridge = dataBaseBridge;
    }

    public static List<LinkedHashMap<String, Object>> selectList(String tableName, String selectCols, String strWhere, String strOrder, HashMap<String, Object> paramMap) {
        String sql = "";
        sql = " select " + selectCols + " from " + tableName;
        if (!MiniFlowCommonUtil.isEmpty(strWhere)) {
            sql += " where  " + strWhere;
        }
        if (!MiniFlowCommonUtil.isEmpty(strOrder)) {
            sql += " order by " + strOrder;
        }
        return bridge.findList(sql, paramMap);
    }

    public static List<LinkedHashMap<String, Object>> selectPageList(String tableName, String selectCols, String strWhere, String strOrder, int pageIndex, int pageSize, HashMap<String, Object> paramMap) {
        String sql = "";
        sql = " select " + selectCols + " from " + tableName;
        if (!MiniFlowCommonUtil.isEmpty(strWhere)) {
            sql += " where  " + strWhere;
        }
        if (!MiniFlowCommonUtil.isEmpty(strOrder)) {
            sql += " order by " + strOrder;
        }
        return bridge.findPageList(sql, pageIndex, pageSize, paramMap);
    }

    public static <T> List<T> selectList(Class<T> clazz, String tableName, String selectCols, String strWhere, String strOrder, HashMap<String, Object> paramMap) {
        List<T> result = new ArrayList<>();
        List<LinkedHashMap<String, Object>> dataList = selectList(tableName, selectCols, strWhere, strOrder, paramMap);
        for (LinkedHashMap<String, Object> data : dataList) {
            result.add(convertLinkHashMapToObj(clazz, data));
        }
        return result;
    }

    public static <T> List<T> selectPageList(Class<T> clazz, String tableName, String selectCols, String strWhere, String strOrder, int pageIndex, int pageSize, HashMap<String, Object> paramMap) {
        List<T> result = new ArrayList<>();
        List<LinkedHashMap<String, Object>> dataList = selectPageList(tableName, selectCols, strWhere, strOrder, pageIndex, pageSize, paramMap);
        for (LinkedHashMap<String, Object> data : dataList) {
            result.add(convertLinkHashMapToObj(clazz, data));
        }
        return result;
    }

    public static <T> void insert(T entity) {
        MiniFlowSQLInfo sqlInfo = MiniFlowSQLGenerateUtil.generateInsertInfo(entity);
        executeSQL(sqlInfo.getSqlText(), sqlInfo.getParamMap());
    }

    public static <T> void update(T entity) {
        MiniFlowSQLInfo sqlInfo = MiniFlowSQLGenerateUtil.generateUpdateInfo(entity);
        executeSQL(sqlInfo.getSqlText(), sqlInfo.getParamMap());
    }

    public static int executeSQL(String sqlText, Map<String, Object> paramMap) {
        return bridge.executeSQL(sqlText, paramMap);
    }

    public static Object executeScar(String sqlText, Map<String, Object> paramMap) {
        return bridge.executeScar(sqlText, paramMap);
    }

    public static <T> T convertLinkHashMapToObj(Class<T> clazz, LinkedHashMap<String, Object> data) {
        T obj = null;
        LinkedHashMap<String, Object> convertData = new LinkedHashMap<>();
        for (String key : data.keySet()) {
            convertData.put(key.toLowerCase(), data.get(key));
        }
        try {
            obj = clazz.newInstance();
            List<Field> fieldList = MiniFlowReflectUtil.getAllFields(clazz);
            for (Field field : fieldList) {
                field.setAccessible(true);
                if (convertData.containsKey(field.getName().toLowerCase())) {
                    field.set(obj, convertData.get(field.getName().toLowerCase()));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}
